<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

class Product extends Model
{
    const TYPE_NORMAL = 'normal';
    const TYPE_CROWDFUNDING = 'crowdfunding';
    const TYPE_SECKILL = 'seckill';

    public static $typeMap = [
        self::TYPE_NORMAL => '普通商品',
        self::TYPE_CROWDFUNDING => '众筹商品',
        self::TYPE_SECKILL => '秒杀商品',
    ];

    /**
     * 可以被批量赋值的属性
     *
     * @var array
     */
    protected $fillable = [
        'type',
        'long_title',
        'title',
        'description',
        'image',
        'on_sale',
        'rating',
        'sold_count',
        'review_count',
        'price',
    ];

    /**
     * 应进行类型转换的属性
     *
     * @var array
     */
    protected $casts = [
        'on_sale' => 'boolean', // on_sale 是一个布尔类型的字段
    ];

    /**
     * 获取图片地址
     *
     * @return mixed
     */
    public function getImageUrlAttribute()
    {
        // 如果 image 字段本身就已经是完整的 url 就直接返回
        if (Str::startsWith($this->attributes['image'], ['http://', 'https://'])) {
            return $this->attributes['image'];
        }

        return \Storage::disk('public')->url($this->attributes['image']);
    }

    /**
     * 与商品SKU关联
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function skus()
    {
        return $this->hasMany(ProductSku::class);
    }

    /**
     * 商品类目
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    /**
     * 众筹商品
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function crowdfunding()
    {
        return $this->hasOne(CrowdfundingProduct::class);
    }

    /**
     * 秒杀商品
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function seckill()
    {
        return $this->hasOne(SeckillProduct::class);
    }

    /**
     * 获取商品属性
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function properties()
    {
        return $this->hasMany(ProductProperty::class);
    }

    /**
     * 获取商品属性
     *
     * @return mixed
     */
    public function getGroupedPropertiesAttribute()
    {
        return $this->properties
            // 按照属性名聚合，返回的结合的 key 是属性名，value 是包含该属性名的所有属性集合
            ->groupBy('name')
            ->map(
                function ($properties) {
                    // 使用 map 方法将属性集合变为属性值集合
                    return $properties->pluck('value')->all();
                }
            );
    }

    public function toESArray()
    {
        // 只取出需要的字段
        $arr = Arr::only(
            $this->toArray(),
            [
                'id',
                'type',
                'title',
                'long_title',
                'category_id',
                'on_sale',
                'rating',
                'sold_count',
                'review_count',
                'price',
            ]
        );

        // 如果商品有类目，则 category 字段为类目名数组，否则为空字符串
        $arr['category'] = $this->category ? explode(' - ', $this->category->full_name) : '';
        // 类目的 path 字段
        $arr['category_path'] = $this->category ? $this->category->path : '';
        // strip_tags 函数可以将 html 标签去除
        $arr['description'] = strip_tags($this->description);
        // 只取出需要的 SKU 字段
        $arr['skus'] = $this->skus->map(
            function (ProductSku $sku) {
                return Arr::only($sku->toArray(), ['title', 'description', 'price']);
            }
        );
        // 只取出需要的商品属性字段
        $arr['properties'] = $this->properties->map(
            function (ProductProperty $property) {
                // 对应地增加一个 search_value 字段，用符号 : 将属性名和属性值拼接起来
                return array_merge(
                    Arr::only($property->toArray(), ['name', 'value']),
                    [
                        'search_value' => $property->name.':'.$property->value,
                    ]
                );
            }
        );

        return $arr;
    }

    /**
     * 商品排序
     *
     * @param $query
     * @param $ids
     * @return mixed
     */
    public function scopeByIds($query, $ids)
    {
        return $query->whereIn('id', $ids)->orderByRaw(sprintf("FIND_IN_SET(id, '%s')", join(',', $ids)));
    }
}
